/*
 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.java.swing.plaf.motif;

import javax.swing.*;

import javax.swing.plaf.UIResource;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Polygon;

import java.io.Serializable;

/**
 * Icon factory for the CDE/Motif Look and Feel
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases.  The current serialization support is appropriate
 * for short term storage or RMI between applications running the same
 * version of Swing.  A future release of Swing will provide support for
 * long term persistence.
 * <p>
 * 1.20 04/27/99
 *
 * @author Georges Saab
 */
public class MotifIconFactory implements Serializable {
    private static Icon checkBoxIcon;
    private static Icon radioButtonIcon;
    private static Icon menuItemCheckIcon;
    private static Icon menuItemArrowIcon;
    private static Icon menuArrowIcon;

    public static Icon getMenuItemCheckIcon() {
        return null;
    }

    public static Icon getMenuItemArrowIcon() {
        if (menuItemArrowIcon == null) {
            menuItemArrowIcon = new MenuItemArrowIcon();
        }
        return menuItemArrowIcon;
    }

    public static Icon getMenuArrowIcon() {
        if (menuArrowIcon == null) {
            menuArrowIcon = new MenuArrowIcon();
        }
        return menuArrowIcon;
    }

    public static Icon getCheckBoxIcon() {
        if (checkBoxIcon == null) {
            checkBoxIcon = new CheckBoxIcon();
        }
        return checkBoxIcon;
    }

    public static Icon getRadioButtonIcon() {
        if (radioButtonIcon == null) {
            radioButtonIcon = new RadioButtonIcon();
        }
        return radioButtonIcon;
    }

    private static class CheckBoxIcon implements Icon, UIResource, Serializable {
        final static int csize = 13;

        private Color control = UIManager.getColor("control");
        private Color foreground = UIManager.getColor("CheckBox.foreground");
        private Color shadow = UIManager.getColor("controlShadow");
        private Color highlight = UIManager.getColor("controlHighlight");
        private Color lightShadow = UIManager.getColor("controlLightShadow");

        public void paintIcon(Component c, Graphics g, int x, int y) {
            AbstractButton b = (AbstractButton) c;
            ButtonModel model = b.getModel();

            boolean flat = false;

            if (b instanceof JCheckBox) {
                flat = ((JCheckBox) b).isBorderPaintedFlat();
            }

            boolean isPressed = model.isPressed();
            boolean isArmed = model.isArmed();
            boolean isEnabled = model.isEnabled();
            boolean isSelected = model.isSelected();

            // There are 4 "looks" to the Motif CheckBox:
            //  drawCheckBezelOut  -  default unchecked state
            //  drawBezel          -  when we uncheck in toggled state
            //  drawCheckBezel     -  when we check in toggle state
            //  drawCheckBezelIn   -  selected, mouseReleased
            boolean checkToggleIn = ((isPressed &&
                    !isArmed &&
                    isSelected) ||
                    (isPressed &&
                            isArmed &&
                            !isSelected));
            boolean uncheckToggleOut = ((isPressed &&
                    !isArmed &&
                    !isSelected) ||
                    (isPressed &&
                            isArmed &&
                            isSelected));

            boolean checkIn = (!isPressed &&
                    isArmed &&
                    isSelected ||
                    (!isPressed &&
                            !isArmed &&
                            isSelected));


            if (flat) {
                g.setColor(shadow);
                g.drawRect(x + 2, y, csize - 1, csize - 1);
                if (uncheckToggleOut || checkToggleIn) {
                    g.setColor(control);
                    g.fillRect(x + 3, y + 1, csize - 2, csize - 2);
                }
            }

            if (checkToggleIn) {
                // toggled from unchecked to checked
                drawCheckBezel(g, x, y, csize, true, false, false, flat);
            } else if (uncheckToggleOut) {
                // MotifBorderFactory.drawBezel(g,x,y,csize,csize,false,false);
                drawCheckBezel(g, x, y, csize, true, true, false, flat);
            } else if (checkIn) {
                // show checked, unpressed state
                drawCheckBezel(g, x, y, csize, false, false, true, flat);
            } else if (!flat) {
                //  show unchecked state
                drawCheckBezelOut(g, x, y, csize);
            }
        }

        public int getIconWidth() {
            return csize;
        }

        public int getIconHeight() {
            return csize;
        }

        public void drawCheckBezelOut(Graphics g, int x, int y, int csize) {
            Color controlShadow = UIManager.getColor("controlShadow");

            int w = csize;
            int h = csize;
            Color oldColor = g.getColor();

            g.translate(x, y);
            g.setColor(highlight);    // inner 3D border
            g.drawLine(0, 0, 0, h - 1);
            g.drawLine(1, 0, w - 1, 0);

            g.setColor(shadow);         // black drop shadow  __|
            g.drawLine(1, h - 1, w - 1, h - 1);
            g.drawLine(w - 1, h - 1, w - 1, 1);
            g.translate(-x, -y);
            g.setColor(oldColor);
        }

        public void drawCheckBezel(Graphics g, int x, int y, int csize,
                                   boolean shade, boolean out, boolean check, boolean flat) {


            Color oldColor = g.getColor();
            g.translate(x, y);


            //bottom
            if (!flat) {
                if (out) {
                    g.setColor(control);
                    g.fillRect(1, 1, csize - 2, csize - 2);
                    g.setColor(shadow);
                } else {
                    g.setColor(lightShadow);
                    g.fillRect(0, 0, csize, csize);
                    g.setColor(highlight);
                }

                g.drawLine(1, csize - 1, csize - 2, csize - 1);
                if (shade) {
                    g.drawLine(2, csize - 2, csize - 3, csize - 2);
                    g.drawLine(csize - 2, 2, csize - 2, csize - 1);
                    if (out) {
                        g.setColor(highlight);
                    } else {
                        g.setColor(shadow);
                    }
                    g.drawLine(1, 2, 1, csize - 2);
                    g.drawLine(1, 1, csize - 3, 1);
                    if (out) {
                        g.setColor(shadow);
                    } else {
                        g.setColor(highlight);
                    }
                }
                //right
                g.drawLine(csize - 1, 1, csize - 1, csize - 1);

                //left
                if (out) {
                    g.setColor(highlight);
                } else {
                    g.setColor(shadow);
                }
                g.drawLine(0, 1, 0, csize - 1);

                //top
                g.drawLine(0, 0, csize - 1, 0);
            }

            if (check) {
                // draw check
                g.setColor(foreground);
                g.drawLine(csize - 2, 1, csize - 2, 2);
                g.drawLine(csize - 3, 2, csize - 3, 3);
                g.drawLine(csize - 4, 3, csize - 4, 4);
                g.drawLine(csize - 5, 4, csize - 5, 6);
                g.drawLine(csize - 6, 5, csize - 6, 8);
                g.drawLine(csize - 7, 6, csize - 7, 10);
                g.drawLine(csize - 8, 7, csize - 8, 10);
                g.drawLine(csize - 9, 6, csize - 9, 9);
                g.drawLine(csize - 10, 5, csize - 10, 8);
                g.drawLine(csize - 11, 5, csize - 11, 7);
                g.drawLine(csize - 12, 6, csize - 12, 6);
            }
            g.translate(-x, -y);
            g.setColor(oldColor);
        }
    } // end class CheckBoxIcon

    private static class RadioButtonIcon implements Icon, UIResource, Serializable {
        private Color dot = UIManager.getColor("activeCaptionBorder");
        private Color highlight = UIManager.getColor("controlHighlight");
        private Color shadow = UIManager.getColor("controlShadow");

        public void paintIcon(Component c, Graphics g, int x, int y) {
            // fill interior
            AbstractButton b = (AbstractButton) c;
            ButtonModel model = b.getModel();

            int w = getIconWidth();
            int h = getIconHeight();

            boolean isPressed = model.isPressed();
            boolean isArmed = model.isArmed();
            boolean isEnabled = model.isEnabled();
            boolean isSelected = model.isSelected();

            boolean checkIn = ((isPressed &&
                    !isArmed &&
                    isSelected) ||
                    (isPressed &&
                            isArmed &&
                            !isSelected)
                    ||
                    (!isPressed &&
                            isArmed &&
                            isSelected ||
                            (!isPressed &&
                                    !isArmed &&
                                    isSelected)));

            if (checkIn) {
                g.setColor(shadow);
                g.drawLine(x + 5, y + 0, x + 8, y + 0);
                g.drawLine(x + 3, y + 1, x + 4, y + 1);
                g.drawLine(x + 9, y + 1, x + 9, y + 1);
                g.drawLine(x + 2, y + 2, x + 2, y + 2);
                g.drawLine(x + 1, y + 3, x + 1, y + 3);
                g.drawLine(x, y + 4, x, y + 9);
                g.drawLine(x + 1, y + 10, x + 1, y + 10);
                g.drawLine(x + 2, y + 11, x + 2, y + 11);
                g.setColor(highlight);
                g.drawLine(x + 3, y + 12, x + 4, y + 12);
                g.drawLine(x + 5, y + 13, x + 8, y + 13);
                g.drawLine(x + 9, y + 12, x + 10, y + 12);
                g.drawLine(x + 11, y + 11, x + 11, y + 11);
                g.drawLine(x + 12, y + 10, x + 12, y + 10);
                g.drawLine(x + 13, y + 9, x + 13, y + 4);
                g.drawLine(x + 12, y + 3, x + 12, y + 3);
                g.drawLine(x + 11, y + 2, x + 11, y + 2);
                g.drawLine(x + 10, y + 1, x + 10, y + 1);
                g.setColor(dot);
                g.fillRect(x + 4, y + 5, 6, 4);
                g.drawLine(x + 5, y + 4, x + 8, y + 4);
                g.drawLine(x + 5, y + 9, x + 8, y + 9);
            } else {
                g.setColor(highlight);
                g.drawLine(x + 5, y + 0, x + 8, y + 0);
                g.drawLine(x + 3, y + 1, x + 4, y + 1);
                g.drawLine(x + 9, y + 1, x + 9, y + 1);
                g.drawLine(x + 2, y + 2, x + 2, y + 2);
                g.drawLine(x + 1, y + 3, x + 1, y + 3);
                g.drawLine(x, y + 4, x, y + 9);
                g.drawLine(x + 1, y + 10, x + 1, y + 10);
                g.drawLine(x + 2, y + 11, x + 2, y + 11);

                g.setColor(shadow);
                g.drawLine(x + 3, y + 12, x + 4, y + 12);
                g.drawLine(x + 5, y + 13, x + 8, y + 13);
                g.drawLine(x + 9, y + 12, x + 10, y + 12);
                g.drawLine(x + 11, y + 11, x + 11, y + 11);
                g.drawLine(x + 12, y + 10, x + 12, y + 10);
                g.drawLine(x + 13, y + 9, x + 13, y + 4);
                g.drawLine(x + 12, y + 3, x + 12, y + 3);
                g.drawLine(x + 11, y + 2, x + 11, y + 2);
                g.drawLine(x + 10, y + 1, x + 10, y + 1);

            }
        }

        public int getIconWidth() {
            return 14;
        }

        public int getIconHeight() {
            return 14;
        }
    } // end class RadioButtonIcon

    private static class MenuItemCheckIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
        }

        public int getIconWidth() {
            return 0;
        }

        public int getIconHeight() {
            return 0;
        }
    }  // end class MenuItemCheckIcon


    private static class MenuItemArrowIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
        }

        public int getIconWidth() {
            return 0;
        }

        public int getIconHeight() {
            return 0;
        }
    }  // end class MenuItemArrowIcon

    private static class MenuArrowIcon implements Icon, UIResource, Serializable {
        private Color focus = UIManager.getColor("windowBorder");
        private Color shadow = UIManager.getColor("controlShadow");
        private Color highlight = UIManager.getColor("controlHighlight");

        public void paintIcon(Component c, Graphics g, int x, int y) {
            AbstractButton b = (AbstractButton) c;
            ButtonModel model = b.getModel();

            // These variables are kind of pointless as the following code
            // assumes the icon will be 10 x 10 regardless of their value.
            int w = getIconWidth();
            int h = getIconHeight();

            Color oldColor = g.getColor();

            if (model.isSelected()) {
                if (MotifGraphicsUtils.isLeftToRight(c)) {
                    g.setColor(shadow);
                    g.fillRect(x + 1, y + 1, 2, h);
                    g.drawLine(x + 4, y + 2, x + 4, y + 2);
                    g.drawLine(x + 6, y + 3, x + 6, y + 3);
                    g.drawLine(x + 8, y + 4, x + 8, y + 5);
                    g.setColor(focus);
                    g.fillRect(x + 2, y + 2, 2, h - 2);
                    g.fillRect(x + 4, y + 3, 2, h - 4);
                    g.fillRect(x + 6, y + 4, 2, h - 6);
                    g.setColor(highlight);
                    g.drawLine(x + 2, y + h, x + 2, y + h);
                    g.drawLine(x + 4, y + h - 1, x + 4, y + h - 1);
                    g.drawLine(x + 6, y + h - 2, x + 6, y + h - 2);
                    g.drawLine(x + 8, y + h - 4, x + 8, y + h - 3);
                } else {
                    g.setColor(highlight);
                    g.fillRect(x + 7, y + 1, 2, 10);
                    g.drawLine(x + 5, y + 9, x + 5, y + 9);
                    g.drawLine(x + 3, y + 8, x + 3, y + 8);
                    g.drawLine(x + 1, y + 6, x + 1, y + 7);
                    g.setColor(focus);
                    g.fillRect(x + 6, y + 2, 2, 8);
                    g.fillRect(x + 4, y + 3, 2, 6);
                    g.fillRect(x + 2, y + 4, 2, 4);
                    g.setColor(shadow);
                    g.drawLine(x + 1, y + 4, x + 1, y + 5);
                    g.drawLine(x + 3, y + 3, x + 3, y + 3);
                    g.drawLine(x + 5, y + 2, x + 5, y + 2);
                    g.drawLine(x + 7, y + 1, x + 7, y + 1);
                }
            } else {
                if (MotifGraphicsUtils.isLeftToRight(c)) {
                    g.setColor(highlight);
                    g.drawLine(x + 1, y + 1, x + 1, y + h);
                    g.drawLine(x + 2, y + 1, x + 2, y + h - 2);
                    g.fillRect(x + 3, y + 2, 2, 2);
                    g.fillRect(x + 5, y + 3, 2, 2);
                    g.fillRect(x + 7, y + 4, 2, 2);
                    g.setColor(shadow);
                    g.drawLine(x + 2, y + h - 1, x + 2, y + h);
                    g.fillRect(x + 3, y + h - 2, 2, 2);
                    g.fillRect(x + 5, y + h - 3, 2, 2);
                    g.fillRect(x + 7, y + h - 4, 2, 2);
                    g.setColor(oldColor);
                } else {
                    g.setColor(highlight);
                    g.fillRect(x + 1, y + 4, 2, 2);
                    g.fillRect(x + 3, y + 3, 2, 2);
                    g.fillRect(x + 5, y + 2, 2, 2);
                    g.drawLine(x + 7, y + 1, x + 7, y + 2);
                    g.setColor(shadow);
                    g.fillRect(x + 1, y + h - 4, 2, 2);
                    g.fillRect(x + 3, y + h - 3, 2, 2);
                    g.fillRect(x + 5, y + h - 2, 2, 2);
                    g.drawLine(x + 7, y + 3, x + 7, y + h);
                    g.drawLine(x + 8, y + 1, x + 8, y + h);
                    g.setColor(oldColor);
                }
            }

        }

        public int getIconWidth() {
            return 10;
        }

        public int getIconHeight() {
            return 10;
        }
    } // End class MenuArrowIcon
}
